#include <json/json.h>
#include <string>


#define REFLECT_PP_FOREACH_1(f, _1) f(_1)
#define REFLECT_PP_FOREACH_2(f, _1, _2) f(_1); f(_2)
#define REFLECT_PP_FOREACH_3(f, _1, _2, _3) f(_1); f(_2); f(_3)
#define REFLECT_PP_FOREACH_4(f, _1, _2, _3, _4) f(_1); f(_2); f(_3); f(_4)
#define REFLECT_PP_FOREACH_5(f, _1, _2, _3, _4, _5) f(_1); f(_2); f(_3); f(_4); f(_5)
#define REFLECT_PP_FOREACH_6(f, _1, _2, _3, _4, _5, _6) f(_1); f(_2); f(_3); f(_4); f(_5); f(_6)
#define REFLECT_PP_FOREACH_7(f, _1, _2, _3, _4, _5, _6, _7) f(_1); f(_2); f(_3); f(_4); f(_5); f(_6); f(_7)
#define REFLECT_PP_FOREACH_8(f, _1, _2, _3, _4, _5, _6, _7, _8) f(_1); f(_2); f(_3); f(_4); f(_5); f(_6); f(_7); f(_8)
#define REFLECT_PP_FOREACH_9(f, _1, _2, _3, _4, _5, _6, _7, _8, _9) f(_1); f(_2); f(_3); f(_4); f(_5); f(_6); f(_7); f(_8); f(_9)
#define REFLECT_PP_FOREACH_10(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) f(_1); f(_2); f(_3); f(_4); f(_5); f(_6); f(_7); f(_8); f(_9); f(_10)

#define REFLECT_PP_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define REFLECT_PP_NARGS(...) REFLECT_PP_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

#define REFLECT_EXPAND(x) x
#define REFLECT_CONCAT_2(x, y) x##y
#define REFLECT_CONCAT(x, y) REFLECT_CONCAT_2(x, y)
#define REFLECT_PP_FOREACH(f, ...) REFLECT_EXPAND(REFLECT_CONCAT(REFLECT_PP_FOREACH_, REFLECT_PP_NARGS(__VA_ARGS__))(f, __VA_ARGS__))

template <class T>
struct reflect_trait{
    template<class Func>
    static constexpr void for_each_members(T& object, Func&& func) {
        object.for_each_members(func);
    }
};

#define REFLECT_PER_MEMBER(x) \
    func(#x, x);

#define REFLECT(...) \
template <class Func> \
constexpr void for_each_members(Func&& func) { \
    REFLECT_PP_FOREACH(REFLECT_PER_MEMBER, __VA_ARGS__) \
}


template <class T>
std::string serialize(T& object)
{
    Json::Value root;
    reflect_trait<T>::for_each_members(object, [&](const std::string& key, auto& value){
        root[key] = value;
    });

    Json::StreamWriterBuilder builder;
    // 去掉缩进，紧凑输出
    builder["indentation"] = "";
    std::string output = Json::writeString(builder, root);
    return output;
}

//======================================================

// 用于处理结构体中有模板参数的情况
#define REFLECT_TYPE_BEGIN(Type, ...) \
template <__VA_ARGS__> \
struct reflect_trait<Type> { \
    template<class Func> \
    static constexpr void for_each_members(Type& object, Func&& func) { \

#define REFLECT_TYPE_PER_MEMBER(Member) \
    func(#Member, object.Member); 

#define REFLECT_TYPE_END() \
    } \
}; \


// 用宏简化模板特化，支持不定参数个数
#define REFLECT_TYPE(Type, ...)\
REFLECT_TYPE_BEGIN(Type) \
REFLECT_PP_FOREACH(REFLECT_TYPE_PER_MEMBER, __VA_ARGS__) \
REFLECT_TYPE_END();

#define REFLECT_TYPE_TEMPLATED(Type, ...) \
REFLECT_EXPAND(REFLECT_TYPE_BEGIN Type) \
REFLECT_PP_FOREACH(REFLECT_TYPE_PER_MEMBER, __VA_ARGS__) \
REFLECT_TYPE_END();


//======================================================

template<class T>
T deserialize(std::string& json)
{
    Json::Value root;
    Json::Reader reader;
    if (!reader.parse(json, root)) {
        throw std::runtime_error("Failed to parse JSON");
    }

    T object;
    reflect_trait<T>::for_each_members(object, [&](const std::string& key, auto& value){
        if (root.isMember(key)) {
            // .as<T>() 是 jsoncpp 提供的 API，用来将 JSON 中的值转为想要的 C++ 类型。
            // decltype(value) 用来获取变量 value 的类型  如果 value 是 object.test2 的引用，那 decltype(value) 就是 int&
            // std::decay_t<T> 表示对类型 T 做「类型衰减」
                //去掉引用（int& → int）
                //把数组变成指针（char[10] → char*）
                //把函数类型变成函数指针（int(int) → int(*)(int)）
            value = root[key].as<std::decay_t<decltype(value)>>();
        }
        else 
        {
            throw std::runtime_error("Missing key: " + key);
        }
    });

    return object;
}